#include "_stock_.h"


int N = 3*sizeof(int);
int M = 3*sizeof(float);

bool _stock_::MoveNext()
{
    if(Count == 0)
        return false;
    if(!Curr->next)
        return false;
    else
    {
        Curr = Curr->next;
    }
    return true;
}

bool _stock_::MovePrev()
{
    if(Count == 0)
        return false;
    if(!Curr->prev)
        return false;
    else
    {
        Curr = Curr->prev;
    }
    return true;
}
bool _stock_::RemovePrev()
{
    stock* Temp;
    if(Count == 0)
        return false;
    if(!Curr->prev)
        return false;
    if(!First)
        return false;

    if(Curr == First->next)
    {
        delete First;
        First = 0;
        First = Curr;
        First->prev = 0;
        Count--;
        return true;
    }

    Temp = Curr->prev;
    Curr->prev->prev->next = Curr;
    Curr->prev = Curr->prev->prev;
    delete Temp;
    Temp = 0;
    Count--;
    return true;
}

bool _stock_::RemoveNext()
{
    stock* Temp;
    if(Count == 0)
        return false;
    if(!Curr->next)
        return false;

    if(Curr == End->prev)
    {
        delete End;
        End = 0;
        End = Curr;
        End->next = 0;
        Count--;
        return true;
    }

    Temp = Curr->next;
    Curr->next->next->prev = Curr;
    Curr->next = Curr->next->next;
    delete Temp;
    Temp = 0;
    Count--;
    return true;
}

bool _stock_::RemoveCurrent()
{
    if(Count == 1)
    {
        delete First;
        First = NULL;
        End = NULL;
        Curr = NULL;
        Count--;
        return true;
    }
    if(Curr == First)
    {
        MoveNext();
        RemovePrev();
        return true;
    }
    if(Curr == End)
    {
        MovePrev();
        RemoveNext();
        return true;
    }
    MovePrev();
    RemoveNext();
    return true;
}

void _stock_::addFirst(int day, int mon, int year, float count, float trade_price, float price_sale)
{
    First = new stock;
    First->Shipment = new Group;
    First->Shipment->dateR = new Data;

    First->Shipment->dateR->day = day;
    First->Shipment->dateR->mon = mon;
    First->Shipment->dateR->year = year;

    First->Shipment->count = count;
    First->Shipment->trade_price = trade_price;
    First->Shipment->price_sale = price_sale;

    First->next = NULL;
    First->prev = NULL;

    End = First;
    Curr = First;

    Count++;
}



_stock_::_stock_() : Count(0)
{
    list->init();
}

_stock_::~_stock_()
{
    list->deinit();
}

bool _stock_::addNext(int day, int mon, int year, float count, float trade_price, float price_sale)
{
    Curr = End;
    if(Count == 0)
    {
        addFirst(day,mon,year,count,trade_price,price_sale);
        return true;
    }

    stock* temp;
    temp = new stock;
    temp->Shipment = new Group;
    temp->Shipment->dateR = new Data;

    if(Curr == End)
    {
        temp->Shipment->dateR->day = day;
        temp->Shipment->dateR->mon = mon;
        temp->Shipment->dateR->year = year;

        temp->Shipment->count = count;
        temp->Shipment->trade_price = trade_price;
        temp->Shipment->price_sale = price_sale;

        temp->prev = End;
        temp->next = NULL;
        Curr->next = temp;
        End = temp;
        Curr = temp;

        Count++;
        return true;
    }
    return false;
}

void _stock_::print()//Вывод базы на экран
{
    if(Count == 0)
    {
        printf("Error: no item\n");
    }
    if(Count < 0)
    {
        printf("Error\n");
    }
    if(Count > 0)
    {
        stock* temp = First;

        printf("\n| DATA       | COUNT               | TRADE PRICE         |  SALE               |\n");
        do
        {
            printf("| %d%d.",(First->Shipment->dateR->day)/10,(First->Shipment->dateR->day) - (First->Shipment->dateR->day/10*10));
            printf("%d%d.",(First->Shipment->dateR->mon)/10,(First->Shipment->dateR->mon) - (First->Shipment->dateR->mon/10*10));
            printf("%d | ",(First->Shipment->dateR->year));
            printf("%19.2f | ",First->Shipment->count);
            printf("%19.2f | ",First->Shipment->trade_price);
            printf("%19.2f |\n",First->Shipment->price_sale);
            First = First->next;
        }while(First!=NULL);
        First = temp;
    }
}

void _stock_::printHistory()
{
    list->print();
}

void _stock_::saveHistory()
{
    list->save();
}

void _stock_::loadHistory()
{
    list->deinit();
    list->init();
    list->load();
}

void _stock_::save_of_one(int day, int mon, int year, float count, float t_p, float p_s, int key)//Функция сохранения одной партии
{
    FILE *f;
    if(key == 0)
        f = fopen("bd.dat","wb");
    else
        f = fopen("bd.dat","ab");

    char* line = new char[N+M];
    char* psVar;
    char* psVam;

    psVar = (char*)&day;
    for(unsigned int i = 0; i < sizeof(int); i++)
    {
        line[i] = psVar[i];
    }

    psVar = (char*)&mon;
    for(unsigned int i = 0; i < sizeof(int); i++)
    {
        line[sizeof(int) + i] = psVar[i];
    }

    psVar = (char*)&year;
    for(unsigned int i = 0; i < sizeof(int); i++)
    {
        line[2*sizeof(int) + i] = psVar[i];
    }
    //delete psVar;

    psVam = (char*)&count;
    for(unsigned int j = 0; j < sizeof(float); j++)
    {
        line[N + j] = psVam[j];
    }

    psVam = (char*)&t_p;
    for(unsigned int j = 0; j < sizeof(float); j++)
    {
        line[N + sizeof(float) + j] = psVam[j];
    }

    psVam = (char*)&p_s;
    for(unsigned int j = 0; j < sizeof(float); j++)
    {
        line[N + 2*sizeof(float) + j] = psVam[j];
    }
    fwrite(line,N+M,1,f);
    fclose(f);
    delete line;
}

bool _stock_::save()//Функция сохранения всей базы
{
    if(Count > 0)
    {
        stock* temp = First;
        int key = 0;
        do
        {
            save_of_one(First->Shipment->dateR-> day,
                        First->Shipment->dateR->mon,
                        First->Shipment->dateR->year,
                        First->Shipment->count,
                        First->Shipment->trade_price,
                        First->Shipment->price_sale,key);
            First = First->next;
            key++;
        }
        while(First!=NULL);
        First = temp;
        return true;
    }
    return false;
}

int _stock_::countEntriesFile()
{
    FILE* f;
    int count = 0;
    f = fopen("bd.dat","rb");
    if(!f)
    {
        std::cout<<f<<std::endl;
        count = 0;
        return count;
    }
    char* line = new char[M+N];
    while(feof(f) == 0)
    {
        fread(line,M+N,1,f);
        count++;
    }
    count--;
    fclose(f);
    return count;
}

void _stock_::deserialization(int &day, int &mon, int &year, float &count, float &t_p, float &p_s,char* line)
{
    char* psVar = new char[N];
    char* psVam = new char[M];

    for(unsigned int i = 0; i < sizeof(int); i++)
    {
        psVar[i] = line[i];
    }
    day = *((int*)psVar);

    for(unsigned int i = 0; i < sizeof(int); i++)
    {
        psVar[i] = line[sizeof(int) + i];
    }
    mon = *((int*)psVar);

    for(unsigned int i = 0; i < sizeof(int); i++)
    {
        psVar[i] = line[2*sizeof(int) + i];
    }
    year = *((int*)psVar);
    delete psVar;


    for(unsigned int j = 0; j < sizeof(float); j++)
    {
        psVam[j] = line[N + j];
    }
    count= *((float*)psVam);

    for(unsigned int j = 0; j < sizeof(float); j++)
    {
        psVam[j] = line[N + sizeof(float) + j];
    }
    t_p= *((float*)psVam);

    for(unsigned int j = 0; j < sizeof(float); j++)
    {
        psVam[j] = line[N + 2*sizeof(float) + j];
    }
    p_s= *((float*)psVam);

    delete psVam;
}

bool _stock_::loadBase()
{
    FILE* f;
    f = fopen("bd.dat","rb");
    if (!f)
        return false;
    int counts = countEntriesFile();
    if(counts == 0)
        return false;
    int day,mon,year;
    float count,trade_price,price_sale;
    char* line = new char[N+M];

    for (int i = 0; i<counts; i++)
    {
        fread(line,M+N,1,f);
        deserialization(day,mon,year,count,trade_price,price_sale,line);
        addNext(day,mon,year,count,trade_price,price_sale);
    }

    fclose(f);
    return true;
}

int _stock_::search(int date_d,int date_m, int date_y, float count)
{
    if(Count == 0)
    {
        return 0;
    }
    if(Count < 0)
    {
        return 0;
    }
    if(Count > 0)
    {
        stock* temp = First;
        do
        {
            if(temp->Shipment->dateR->day == date_d and temp->Shipment->dateR->mon == date_m and temp->Shipment->dateR->year == date_y)
            {
                if(temp->Shipment ->count == count)
                {
                    //сохраняем элемент который удаляем в историю
                    historyData data;
                    data.data = *temp->Shipment->dateR;
                    data.count = temp->Shipment ->count;
                    data.TradePrice = temp->Shipment->trade_price;
                    data.SalePrice = temp->Shipment->price_sale;
                    list->pushBack(data);

                    Curr = temp;
                    RemoveCurrent();
                    return 1;
                }
                if(temp->Shipment ->count > count)
                {
                    temp->Shipment ->count -= count;
                    //сохраняем элемент который удаляем в историю
                    historyData data;
                    data.data = *temp->Shipment->dateR;
                    data.count = count;
                    data.TradePrice = temp->Shipment->trade_price;
                    data.SalePrice = temp->Shipment->price_sale;
                    list->pushBack(data);
                }
                else if(temp->Shipment ->count < count)
                    return 2;
            }
            temp = temp->next;
        }
        while(temp!=NULL);
    }
    return true;
}
